package com.jl.stk.ui.actions;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.wb.swt.ResourceManager;
import org.eclipse.wb.swt.SWTResourceManager;

import com.jl.card.Card;
import com.jl.card.CardManager;
import com.jl.card.ISTK;
import com.jl.card.JL;
import com.jl.card.RefreshListenner;
import com.jl.card.provider.jl2g.STKUIControl;
import com.jl.card.stk.STKManager;
import com.jl.util.SWTDialogUtil;
import org.eclipse.swt.widgets.Label;

public class STKDialog extends Dialog implements RefreshListenner {

	private ISTK stk;
	private Card card;
	String[] entry;
	private STKUIControl ui;
	private static STKDialog dialog;

	protected Object result;
	protected Shell shlStk;
	private Text textInput;
	private List listItem;
	private Button btnOk;
	private Button btnBack;
	private Button btnEnvelop;
	private Button btnOn;
	private Composite compositeDisplayText;
	private Text text;
	private Composite compositeItems;
	private Composite composite;
	private Text textEnvelop;
	private boolean isOpening;
	private Button btnOff;
	private Combo comboCards;
	private Composite composite_2;
	private String[] names = new String[0];
	private Label lblAlpha;

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	private STKDialog(Shell parent, int style) {
		super(parent, style);
		setText("STK Dialog");
		createContents();
		CardManager.getInstance().addRefreshListenner(this);
	}

	public static synchronized STKDialog getInstance(Shell parent, int style) {
		if (dialog == null) {
			dialog = new STKDialog(parent, style);
		}
		return dialog;
	}

	/**
	 * Open the dialog.
	 * 
	 * @return the result
	 */
	public Object open() {

		Display display = getParent().getDisplay();
		SWTDialogUtil.locateToParentCenter(getParent(), shlStk);
		((StackLayout) composite.getLayout()).topControl = compositeItems;
		shlStk.open();
		shlStk.layout();
		isOpening = true;
		while (!shlStk.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		return result;
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shlStk = new Shell(getParent(), SWT.DIALOG_TRIM);
		shlStk.addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent e) {
				SWTResourceManager.dispose();
			}
		});
		shlStk.setImage(ResourceManager.getPluginImage("com.jl.stk.ui",
				"icons/stk_16.png"));
		shlStk.addShellListener(new ShellAdapter() {
			@Override
			public void shellClosed(ShellEvent e) {
				if (STKDialog.this.btnOff.isEnabled()) {
					pressOff();
				}
				CardManager.getInstance().removeRefreshListenner(dialog);
				dialog = null;
			}
		});
		shlStk.setSize(333, 454);
		shlStk.setText("STK");
		shlStk.setLayout(new GridLayout(1, false));

		composite_2 = new Composite(shlStk, SWT.NONE);
		composite_2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
				false, 1, 1));
		composite_2.setLayout(new GridLayout(1, false));

		comboCards = new Combo(composite_2, SWT.READ_ONLY);
		GridData gd_comboCards = new GridData(SWT.FILL, SWT.CENTER, true,
				false, 1, 1);
		gd_comboCards.widthHint = 253;
		comboCards.setLayoutData(gd_comboCards);
		comboCards.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));
		
		lblAlpha = new Label(shlStk, SWT.NONE);
		GridData gd_lblAlpha = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
		gd_lblAlpha.widthHint = 208;
		lblAlpha.setLayoutData(gd_lblAlpha);
		lblAlpha.setFont(SWTResourceManager.getFont("Courier New", 11, SWT.NORMAL));
		lblAlpha.setText(" ");

		composite = new Composite(shlStk, SWT.NONE);
		composite.setLayout(new StackLayout());
		GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false,
				1, 1);
		gd_composite.heightHint = 221;
		composite.setLayoutData(gd_composite);

		Composite composite_1 = new Composite(shlStk, SWT.NONE);
		composite_1.setLayout(new GridLayout(3, false));
		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true,
				1, 1));

		compositeItems = new Composite(composite, SWT.NONE);
		compositeItems.setLayout(new GridLayout(1, false));

		listItem = new List(compositeItems, SWT.BORDER | SWT.V_SCROLL);
		GridData gd_listItem = new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1);
		gd_listItem.heightHint = 171;
		listItem.setLayoutData(gd_listItem);
		listItem.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				doubleClickItem(e);
			}
		});
		listItem.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		compositeDisplayText = new Composite(composite, SWT.NONE);
		compositeDisplayText.setLayout(new GridLayout(1, false));

		text = new Text(compositeDisplayText, SWT.BORDER | SWT.READ_ONLY
				| SWT.WRAP);
		text.setFont(SWTResourceManager.getFont("Courier New", 11, SWT.NORMAL));
		GridData gd_text = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
		gd_text.heightHint = 86;
		text.setLayoutData(gd_text);

		textInput = new Text(compositeDisplayText, SWT.BORDER | SWT.READ_ONLY
				| SWT.WRAP);
		textInput.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				event_modify_input_text();
			}
		});
		textInput.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				event_key_pressed_input(e);
			}
		});
		GridData gd_textInput = new GridData(SWT.FILL, SWT.FILL, true, true, 1,
				1);
		gd_textInput.heightHint = 66;
		textInput.setLayoutData(gd_textInput);
		textInput.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		btnOk = new Button(composite_1, SWT.NONE);
		btnOk.setEnabled(false);
		btnOk.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				preseOK();
			}
		});
		btnOk.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1,
				1));
		btnOk.setFont(SWTResourceManager.getFont("Courier New", 11, SWT.NORMAL));
		btnOk.setText("OK");

		btnBack = new Button(composite_1, SWT.NONE);
		btnBack.setEnabled(false);
		btnBack.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				preseBack();
			}
		});
		btnBack.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
				2, 1));
		btnBack.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));
		btnBack.setText("BACK");

		textEnvelop = new Text(composite_1, SWT.BORDER | SWT.WRAP);
		textEnvelop.setEditable(false);
		GridData gd_textEnvelop = new GridData(SWT.FILL, SWT.FILL, true, true,
				3, 1);
		gd_textEnvelop.widthHint = 244;
		textEnvelop.setLayoutData(gd_textEnvelop);
		textEnvelop.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));

		btnEnvelop = new Button(composite_1, SWT.NONE);
		btnEnvelop.setEnabled(false);
		btnEnvelop.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				pressEnvelop();
			}
		});
		btnEnvelop.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
				false, 1, 1));
		btnEnvelop.setFont(SWTResourceManager.getFont("Courier New", 11,
				SWT.NORMAL));
		btnEnvelop.setText("ENVELOP");

		btnOn = new Button(composite_1, SWT.NONE);
		btnOn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				pressOn();
			}
		});
		GridData gd_btnOn = new GridData(SWT.FILL, SWT.CENTER, true, false, 1,
				1);
		gd_btnOn.widthHint = 7;
		btnOn.setLayoutData(gd_btnOn);
		btnOn.setFont(SWTResourceManager.getFont("Courier New", 11, SWT.NORMAL));
		btnOn.setText("ON");

		btnOff = new Button(composite_1, SWT.NONE);
		btnOff.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				pressOff();
			}
		});
		btnOff.setEnabled(false);
		GridData gd_btnOff = new GridData(SWT.LEFT, SWT.CENTER, false, false,
				1, 1);
		gd_btnOff.widthHint = 64;
		btnOff.setLayoutData(gd_btnOff);
		btnOff.setFont(SWTResourceManager
				.getFont("Courier New", 11, SWT.NORMAL));
		btnOff.setText("OFF");

	}

	protected void pressOff() {
		if (stk.getUI() != null) {
			stk.off();
		}
		setUICloseState();
	}

	protected void event_modify_input_text() {
		if (!(ui.isGetInput() || ui.isGetInkey()) ) {
			return;
		}
		int len = this.textInput.getText().length();
		if (len >= ui.getInputMin() && len <= ui.getInputMax()) {
			this.btnOk.setEnabled(true);
		} else {
			this.btnOk.setEnabled(false);
		}
	}

	protected void event_key_pressed_input(KeyEvent e) {
		if (this.textInput.getEditable()) {
			if (this.textInput.getText().length() >= ui.getInputMax()) {
				if (isControl(e.character)) {
					e.doit = true;
					return;
				}
				e.doit = false;
				return;
			}

			if (ui.getInputType() == JL.STK_INPUT_NUM) {
				if (!isNum(e.character)) {
					e.doit = false;
				}
			}
			if (ui.getInputType() == JL.STK_INPUT_ASC) {
				if (!isASC(e.character)) {
					e.doit = false;
				}
			}
		}
	}

	private boolean isNum(char ch) {
		if (ch >= '0' && ch <= '9' || ch == '*' || ch == '#' || ch == '+') {
			return true;
		}
		if (isControl(ch)) {
			return true;
		}
		return false;
	}

	private boolean isASC(char ch) {
		if (isControl(ch) || ch == '\n') {
			return true;
		}
		return Character.isLetter(ch);
	}

	private boolean isControl(char ch) {
		return Character.isISOControl(ch);
	}

	protected void pressOn() {
		card = CardManager.getInstance().getCardInstanceByName(
				this.comboCards.getItem(this.comboCards.getSelectionIndex()));
		if (card == null) {
			return;
		}
		this.stk = STKManager.getInstance().getSTK(card);
		stk.on();
		this.btnOk.setEnabled(true);
		this.btnBack.setEnabled(true);
		this.btnEnvelop.setEnabled(true);
		this.textEnvelop.setEditable(true);
		this.btnOn.setEnabled(false);
		this.btnOff.setEnabled(true);
		show();
	}

	private void addToList(String[] allItems) {
		this.listItem.setItems(allItems);
		if (allItems.length > 0) {
			this.listItem.select(0);
		}
		((StackLayout) composite.getLayout()).topControl = compositeItems;
		composite.layout();
	}

	protected void pressEnvelop() {
		stk.envelop(this.textEnvelop.getText());
		show();
	}

	protected void preseBack() {
		stk.back();
		show();
	}

	protected void preseOK() {
		if (this.textInput.getEditable()) {
			stk.input(this.textInput.getText());
		} else if (listItem.isVisible() && listItem.getSelectionIndex() != -1) {
			doubleClickItem(null);
		} else {
			stk.ok();
		}
		show();
	}

	protected void doubleClickItem(MouseEvent e) {
		int index = listItem.getSelectionIndex();
		if (index == -1) {
			return;
		}
		listItem.deselect(index);
		stk.select(index + 1);
		show();
	}

	private void show() {
		ui = stk.getUI();
		if (ui == null) {
			addToList(new String[0]);
			this.btnOk.setEnabled(false);
			this.btnBack.setEnabled(false);
		} else {
			//set alpha
			this.lblAlpha.setText(" "+ ui.getAlphaText());
			
			this.btnOk.setEnabled(true);
			this.btnBack.setEnabled(true);
			this.btnEnvelop.setEnabled(true);
			if (ui.isMenu() || ui.isItem()) {
				addToList(ui.getAllItems());
				this.textInput.setEditable(false);
				this.text.setEditable(false);
			} else {
				((StackLayout) composite.getLayout()).topControl = compositeDisplayText;
				composite.layout();
				this.textInput.setText("");
				this.text.setText("");
				this.textInput.setToolTipText("");
				if (ui.isDisplayText()) {
					this.text.setEditable(false);
					this.text.setText(ui.getDisplayText());
				}
				if (ui.isGetInput() || ui.isGetInkey()) {
					this.text.setEditable(false);
					this.text.setText(ui.getDisplayText());
					this.textInput.setEditable(true);
					this.textInput.setFocus();
					this.textInput.setToolTipText(ui.getMoreInfo());
					if (ui.getInputMin() > 0) {
						this.btnOk.setEnabled(false);
					}
				} else {
					this.textInput.setEditable(false);
				}
				if (ui.isSendMessage()) {
					this.text.setEditable(false);
					this.text.setText(ui.getDisplayText());
					this.textInput.setText(ui.getMoreInfo());
					this.btnBack.setEnabled(false);
				}
			}
		}
	}

	public boolean isOpening() {
		return isOpening;
	}

	@Override
	public void refresh() {
		this.setUICloseState();
	}

	private void setUICloseState() {
		this.btnOk.setEnabled(false);
		this.btnBack.setEnabled(false);
		this.btnEnvelop.setEnabled(false);
		this.textEnvelop.setEditable(false);
		this.btnOn.setEnabled(true);
		this.btnOff.setEnabled(false);
		addToList(new String[0]);
	}

	public void setCards(String[] names) {
		this.comboCards.setItems(names);
		this.comboCards.select(0);
	}

}
